using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace XNASubdivision
{
    // this is a geometry shader emulator
    partial class CatmullClarkSubdivider_GS_Imitation
    {

        List<VertexPositionNormalTexture> m_triangleStrip = new List<VertexPositionNormalTexture>();


        private void ProcessQuadLevel0(int p_quadIndex)
        {
            m_triangleStrip.Clear();

            VertexPositionNormalTexture output;
            Int4 quadInd = g_quadBuffer[p_quadIndex];
            Int4 texInd = g_quadTextureIndBuffer[p_quadIndex];
            Int4 normalInd = g_quadNormalIndBuffer[p_quadIndex];

            Vector3 v1 = g_vertBuffer[quadInd.x];
            Vector3 v2 = g_vertBuffer[quadInd.y];
            Vector3 v3 = g_vertBuffer[quadInd.z];
            Vector3 v4 = g_vertBuffer[quadInd.w];

            Vector2 t1 = g_texUvBuffer[texInd.x];
            Vector2 t2 = g_texUvBuffer[texInd.y];
            Vector2 t3 = g_texUvBuffer[texInd.z];
            Vector2 t4 = g_texUvBuffer[texInd.w];

            Vector3 n1 = g_normalBuffer[normalInd.x];
            Vector3 n2 = g_normalBuffer[normalInd.y];
            Vector3 n3 = g_normalBuffer[normalInd.z];
            Vector3 n4 = g_normalBuffer[normalInd.w];

            output.Position = v1;
            output.TextureCoordinate = t1;
            output.Normal = n1;
            m_triangleStrip.Add(output);

            output.Position = v2;
            output.TextureCoordinate = t2;
            output.Normal = n2;
            m_triangleStrip.Add(output);

            output.Position = v3;
            output.TextureCoordinate = t3;
            output.Normal = n3;
            m_triangleStrip.Add(output);

            output.Position = v4;
            output.TextureCoordinate = t4;
            output.Normal = n4;
            m_triangleStrip.Add(output);

            RestartStrip(); 
        }

        private void ProcessQuadLevel1(int p_quadIndex)
        {
            m_triangleStrip.Clear();

            VertexPositionNormalTexture output;
            Int4 quadInd = g_quadBuffer[p_quadIndex];
            Int4 texInd = g_quadTextureIndBuffer[p_quadIndex];
            Int4 normalInd = g_quadNormalIndBuffer[p_quadIndex];

            Vector3 v1 = g_vertBuffer[quadInd.x];
            Vector3 v2 = g_vertBuffer[quadInd.y];
            Vector3 v3 = g_vertBuffer[quadInd.z];
            Vector3 v4 = g_vertBuffer[quadInd.w];

            uint val1 = g_vertValenceBuffer[quadInd.x];
            uint val2 = g_vertValenceBuffer[quadInd.y];
            uint val3 = g_vertValenceBuffer[quadInd.z];
            uint val4 = g_vertValenceBuffer[quadInd.w];

            // v11
            int v11Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex];
            Vector3 v11 = g_vertBuffer[v11Ind];

            int v12Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 1];
            Vector3 v12 = g_vertBuffer[v12Ind];
            int v13Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 2];
            Vector3 v13 = g_vertBuffer[v13Ind];

            int v14Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 3];
            Vector3 v14 = g_vertBuffer[v14Ind];
            int v15Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 4];
            Vector3 v15 = g_vertBuffer[v15Ind];

            int v1LastInd = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + (val1 - 3) * 2];
            Vector3 v1Last = g_vertBuffer[v1LastInd];

            // v21
            int v21Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 5];
            Vector3 v21 = g_vertBuffer[v21Ind];

            int v22Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 6];
            Vector3 v22 = g_vertBuffer[v22Ind];
            int v23Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 7];
            Vector3 v23 = g_vertBuffer[v23Ind];

            int v24Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 8];
            Vector3 v24 = g_vertBuffer[v24Ind];
            int v25Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 9];
            Vector3 v25 = g_vertBuffer[v25Ind];

            int v2LastInd = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 5 + (val2 - 3) * 2];
            Vector3 v2Last = g_vertBuffer[v2LastInd];

            // v31
            int v31Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 10];
            Vector3 v31 = g_vertBuffer[v31Ind];

            int v32Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 11];
            Vector3 v32 = g_vertBuffer[v32Ind];
            int v33Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 12];
            Vector3 v33 = g_vertBuffer[v33Ind];

            int v34Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 13];
            Vector3 v34 = g_vertBuffer[v34Ind];
            int v35Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 14];
            Vector3 v35 = g_vertBuffer[v35Ind];

            int v3LastInd = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 10 + (val3 - 3) * 2];
            Vector3 v3Last = g_vertBuffer[v3LastInd];

            // v41
            int v41Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 15];
            Vector3 v41 = g_vertBuffer[v41Ind];

            int v42Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 16];
            Vector3 v42 = g_vertBuffer[v42Ind];
            int v43Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 17];
            Vector3 v43 = g_vertBuffer[v43Ind];

            int v44Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 18];
            Vector3 v44 = g_vertBuffer[v44Ind];
            int v45Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 19];
            Vector3 v45 = g_vertBuffer[v45Ind];

            int v4LastInd = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 15 + (val4 - 3) * 2];
            Vector3 v4Last = g_vertBuffer[v4LastInd];


            Vector3 a5 = (v1 + v2 + v3 + v4) / 4.0f;
            Vector3 a2 = (6 * (v1 + v2) + v1Last + v21 + v3 + v4) / 16.0f;
            Vector3 a6 = (6 * (v2 + v4) + v2Last + v41 + v1 + v3) / 16.0f;
            Vector3 a8 = (6 * (v4 + v3) + v4Last + v31 + v1 + v2) / 16.0f;
            Vector3 a4 = (6 * (v3 + v1) + v3Last + v11 + v2 + v4) / 16.0f;

            Vector3 a1 = v1;
            if (val1 == 3)
                a1 = (15 * v1 + 6 * (v11 + v2 + v3) + v3Last + v21 + v4) / 36;
            else if (val1 == 4)
                a1 = (36 * v1 + 6 * (v11 + v13 + v2 + v3) + v3Last + v12 + v21 + v4) / 64;
            else
                a1 = (65 * v1 + 6 * (v11 + v13 + v15 + v2 + v3) + v3Last + v12 + v14 + v21 + v4) / 100;
            
            Vector3 a3 = v2;
            if (val2 == 3)
                a3 = (15 * v2 + 6 * (v21 + v1 + v4) + v1Last + v41 + v3) / 36;
            else if (val2 == 4)
                a3 = (36 * v2 + 6 * (v21 + v23 + v1 + v4) + v1Last + v22 + v41 + v3) / 64;
            else
                a3 = (65 * v2 + 6 * (v21 + v23 + v25 + v1 + v4) + v1Last + v22 + v24 + v41 + v3) / 100;

            Vector3 a7 = v3;
            if (val3 == 3)
                a7 = (15 * v3 + 6 * (v31 + v1 + v4) + v4Last + v11 + v2) / 36;
            else if (val3 == 4)
                a7 = (36 * v3 + 6 * (v31 + v33 + v1 + v4) + v4Last + v32 + v11 + v2) / 64;
            else
                a7 = (65 * v3 + 6 * (v31 + v33 + v35 + v1 + v4) + v4Last + v32 + v34 + v11 + v2) / 100;

            Vector3 a9 = v4;
            if (val4 == 3)
                a9 = (15 * v4 + 6 * (v41 + v2 + v3) + v2Last + v31 + v1) / 36;
            else if (val4 == 4)
                a9 = (36 * v4 + 6 * (v41 + v43 + v2 + v3) + v2Last + v42 + v31 + v1) / 64;
            else
                a9 = (65 * v4 + 6 * (v41 + v43 + v45 + v2 + v3) + v2Last + v42 + v44 + v31 + v1) / 100;



            // ********** texture and normal
            Vector2 t1 = g_texUvBuffer[texInd.x];
            Vector2 t3 = g_texUvBuffer[texInd.y];
            Vector2 t7 = g_texUvBuffer[texInd.z];
            Vector2 t9 = g_texUvBuffer[texInd.w];
            Vector2 t2 = (t1 + t3) / 2.0f;
            Vector2 t4 = (t1 + t7) / 2.0f;
            Vector2 t6 = (t3 + t9) / 2.0f;
            Vector2 t8 = (t7 + t9) / 2.0f;
            Vector2 t5 = (t4 + t6) / 2.0f;

            Vector3 n1 = g_normalBuffer[normalInd.x];
            Vector3 n3 = g_normalBuffer[normalInd.y];
            Vector3 n7 = g_normalBuffer[normalInd.z];
            Vector3 n9 = g_normalBuffer[normalInd.w];
            Vector3 n2 = (n1 + n3);
            Vector3 n4 = (n1 + n7);
            Vector3 n6 = (n3 + n9);
            Vector3 n8 = (n7 + n9);
            Vector3 n5 = (n4 + n6);


            output.Position = a3;
            output.TextureCoordinate = t3;
            output.Normal = n3;
            m_triangleStrip.Add(output);

            output.Position = a6;
            output.TextureCoordinate = t6;
            output.Normal = n6;
            m_triangleStrip.Add(output);

            output.Position = a2;
            output.TextureCoordinate = t2;
            output.Normal = n2;
            m_triangleStrip.Add(output);

            output.Position = a5;
            output.TextureCoordinate = t5;
            output.Normal = n5;
            m_triangleStrip.Add(output);

            output.Position = a1;
            output.TextureCoordinate = t1;
            output.Normal = n1;
            m_triangleStrip.Add(output);

            output.Position = a4;
            output.TextureCoordinate = t4;
            output.Normal = n4;
            m_triangleStrip.Add(output);

            RestartStrip();

            output.Position = a6;
            output.TextureCoordinate = t6;
            output.Normal = n6;
            m_triangleStrip.Add(output);

            output.Position = a9;
            output.TextureCoordinate = t9;
            output.Normal = n9;
            m_triangleStrip.Add(output);

            output.Position = a5;
            output.TextureCoordinate = t5;
            output.Normal = n5;
            m_triangleStrip.Add(output);

            output.Position = a8;
            output.TextureCoordinate = t8;
            output.Normal = n8;
            m_triangleStrip.Add(output);

            output.Position = a4;
            output.TextureCoordinate = t4;
            output.Normal = n4;
            m_triangleStrip.Add(output);

            output.Position = a7;
            output.TextureCoordinate = t7;
            output.Normal = n7;
            m_triangleStrip.Add(output);

            RestartStrip(); 

        }

        private void ProcessQuadLevel2(int p_quadIndex)
        {
            m_triangleStrip.Clear();

            VertexPositionNormalTexture output;
            Int4 quadInd = g_quadBuffer[p_quadIndex];
            Int4 texInd = g_quadTextureIndBuffer[p_quadIndex];
            Int4 normalInd = g_quadNormalIndBuffer[p_quadIndex];

            Vector3 v1 = g_vertBuffer[quadInd.x];
            Vector3 v2 = g_vertBuffer[quadInd.y];
            Vector3 v3 = g_vertBuffer[quadInd.z];
            Vector3 v4 = g_vertBuffer[quadInd.w];

            uint val1 = g_vertValenceBuffer[quadInd.x];
            uint val2 = g_vertValenceBuffer[quadInd.y];
            uint val3 = g_vertValenceBuffer[quadInd.z];
            uint val4 = g_vertValenceBuffer[quadInd.w];

            // v11
            int v11Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex];
            Vector3 v11 = g_vertBuffer[v11Ind];

            int v12Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 1];
            Vector3 v12 = g_vertBuffer[v12Ind];
            int v13Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 2];
            Vector3 v13 = g_vertBuffer[v13Ind];

            int v14Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 3];
            Vector3 v14 = g_vertBuffer[v14Ind];
            int v15Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 4];
            Vector3 v15 = g_vertBuffer[v15Ind];

            int v1LastInd = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + (val1 - 3) * 2];
            Vector3 v1Last = g_vertBuffer[v1LastInd];

            // v21
            int v21Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 5];
            Vector3 v21 = g_vertBuffer[v21Ind];

            int v22Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 6];
            Vector3 v22 = g_vertBuffer[v22Ind];
            int v23Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 7];
            Vector3 v23 = g_vertBuffer[v23Ind];

            int v24Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 8];
            Vector3 v24 = g_vertBuffer[v24Ind];
            int v25Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 9];
            Vector3 v25 = g_vertBuffer[v25Ind];

            int v2LastInd = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 5 + (val2 - 3) * 2];
            Vector3 v2Last = g_vertBuffer[v2LastInd];

            // v31
            int v31Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 10];
            Vector3 v31 = g_vertBuffer[v31Ind];

            int v32Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 11];
            Vector3 v32 = g_vertBuffer[v32Ind];
            int v33Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 12];
            Vector3 v33 = g_vertBuffer[v33Ind];

            int v34Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 13];
            Vector3 v34 = g_vertBuffer[v34Ind];
            int v35Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 14];
            Vector3 v35 = g_vertBuffer[v35Ind];

            int v3LastInd = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 10 + (val3 - 3) * 2];
            Vector3 v3Last = g_vertBuffer[v3LastInd];

            // v41
            int v41Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 15];
            Vector3 v41 = g_vertBuffer[v41Ind];

            int v42Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 16];
            Vector3 v42 = g_vertBuffer[v42Ind];
            int v43Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 17];
            Vector3 v43 = g_vertBuffer[v43Ind];

            int v44Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 18];
            Vector3 v44 = g_vertBuffer[v44Ind];
            int v45Ind = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 19];
            Vector3 v45 = g_vertBuffer[v45Ind];

            int v4LastInd = g_quadAdjacentVerticesBuffer[20 * p_quadIndex + 15 + (val4 - 3) * 2];
            Vector3 v4Last = g_vertBuffer[v4LastInd];


            Vector3 a5 = (v1 + v2 + v3 + v4) / 4.0f;
            Vector3 a2 = (6 * (v1 + v2) + v1Last + v21 + v3 + v4) / 16.0f;
            Vector3 a6 = (6 * (v2 + v4) + v2Last + v41 + v1 + v3) / 16.0f;
            Vector3 a8 = (6 * (v4 + v3) + v4Last + v31 + v1 + v2) / 16.0f;
            Vector3 a4 = (6 * (v3 + v1) + v3Last + v11 + v2 + v4) / 16.0f;

            Vector3 a1 = v1;
            if (val1 == 3)
                a1 = (15 * v1 + 6 * (v11 + v2 + v3) + v3Last + v21 + v4) / 36;
            else if (val1 == 4)
                a1 = (36 * v1 + 6 * (v11 + v13 + v2 + v3) + v3Last + v12 + v21 + v4) / 64;
            else
                a1 = (65 * v1 + 6 * (v11 + v13 + v15 + v2 + v3) + v3Last + v12 + v14 + v21 + v4) / 100;

            Vector3 a3 = v2;
            if (val2 == 3)
                a3 = (15 * v2 + 6 * (v21 + v1 + v4) + v1Last + v41 + v3) / 36;
            else if (val2 == 4)
                a3 = (36 * v2 + 6 * (v21 + v23 + v1 + v4) + v1Last + v22 + v41 + v3) / 64;
            else
                a3 = (65 * v2 + 6 * (v21 + v23 + v25 + v1 + v4) + v1Last + v22 + v24 + v41 + v3) / 100;

            Vector3 a7 = v3;
            if (val3 == 3)
                a7 = (15 * v3 + 6 * (v31 + v1 + v4) + v4Last + v11 + v2) / 36;
            else if (val3 == 4)
                a7 = (36 * v3 + 6 * (v31 + v33 + v1 + v4) + v4Last + v32 + v11 + v2) / 64;
            else
                a7 = (65 * v3 + 6 * (v31 + v33 + v35 + v1 + v4) + v4Last + v32 + v34 + v11 + v2) / 100;

            Vector3 a9 = v4;
            if (val4 == 3)
                a9 = (15 * v4 + 6 * (v41 + v2 + v3) + v2Last + v31 + v1) / 36;
            else if (val4 == 4)
                a9 = (36 * v4 + 6 * (v41 + v43 + v2 + v3) + v2Last + v42 + v31 + v1) / 64;
            else
                a9 = (65 * v4 + 6 * (v41 + v43 + v45 + v2 + v3) + v2Last + v42 + v44 + v31 + v1) / 100;

            Vector3 b1 = a1;
            Vector3 b2 = (a1 + a2) / 2.0f;
            Vector3 b3 = a2;
            Vector3 b4 = (a2 + a3) / 2.0f;
            Vector3 b5 = a3;
            Vector3 b6 = (a1 + a4) / 2.0f;
            Vector3 b7 = (a1 + a2 + a4 + a5) / 4.0f;
            Vector3 b8 = (a2 + a5) / 2.0f;
            Vector3 b9 = (a2 + a3 + a5 + a6) / 4.0f;
            Vector3 b10 = (a3 + a6) / 2.0f;
            Vector3 b11 = a4;
            Vector3 b12 = (a4 + a5) / 2.0f;
            Vector3 b13 = a5;
            Vector3 b14 = (a5 + a6) / 2.0f;
            Vector3 b15 = a6;
            Vector3 b16 = (a4 + a7) / 2.0f;
            Vector3 b17 = (a4 + a5 + a7 + a8) / 4.0f;
            Vector3 b18 = (a5 + a8) / 2.0f;
            Vector3 b19 = (a5 + a6 + a8 + a9) / 4.0f;
            Vector3 b20 = (a6 + a9) / 2.0f;
            Vector3 b21 = a7;
            Vector3 b22 = (a7 + a8) / 2.0f;
            Vector3 b23 = a8;
            Vector3 b24 = (a8 + a9) / 2.0f;
            Vector3 b25 = a9;

            Vector3 A11 = (v3Last + v11 + v1 + v3) / 4.0f;
            Vector3 A12 = (v11 + v12 + v13 + v1) / 4.0f;
            Vector3 A13 = (v13 + v14 + v15 + v1) / 4.0f;
                      
            Vector3 A31 = (v1Last + v21 + v2 + v1) / 4.0f;
            Vector3 A32 = (v21 + v22 + v23 + v2) / 4.0f;
            Vector3 A33 = (v23 + v24 + v25 + v2) / 4.0f;
            
            Vector3 A71 = (v4Last + v31 + v3 + v4) / 4.0f;
            Vector3 A72 = (v31 + v32 + v33 + v3) / 4.0f;
            Vector3 A73 = (v33 + v34 + v35 + v3) / 4.0f;
           
            Vector3 A91 = (v2Last + v41 + v4 + v2) / 4.0f;
            Vector3 A92 = (v41 + v42 + v43 + v4) / 4.0f;
            Vector3 A93 = (v43 + v44 + v45 + v4) / 4.0f;
            
            // *****
            Vector3 AA11 = (A11 + A12 + v11 + v1) / 4.0f;
            Vector3 AA12 = (A12 + A13 + v13 + v1) / 4.0f;
            Vector3 AA13 = (A13 + A31 + v15 + v1) / 4.0f;
            Vector3 AA1Last;
            if (val1 == 3)
                AA1Last = (A11 + A31 + v11 + v1) / 4.0f;
            else if (val1 == 4)
                AA1Last = (A12 + A31 + v13 + v1) / 4.0f;
            else
                AA1Last = (A13 + A31 + v15 + v1) / 4.0f;
            Vector3 AA1First;
            if (val1 == 3)
                AA1First = (A11 + A31 + v11 + v1) / 4.0f;
            else
                AA1First = (A11 + A12 + v11 + v1) / 4.0f;
            
            Vector3 AA31 = (A31 + A32 + v21 + v2) / 4.0f;
            Vector3 AA32 = (A32 + A33 + v23 + v2) / 4.0f;
            Vector3 AA33 = (A33 + A91 + v25 + v2) / 4.0f;
            Vector3 AA3Last;
            if (val2 == 3)
                AA3Last = (A31 + A91 + v21 + v2) / 4.0f;
            else if (val2 == 4)
                AA3Last = (A32 + A91 + v23 + v2) / 4.0f;
            else
                AA3Last = (A33 + A91 + v25 + v2) / 4.0f;
            Vector3 AA3First;
            if (val2 == 3)
                AA3First = (A31 + A91 + v21 + v2) / 4.0f;
            else
                AA3First = (A31 + A32 + v21 + v2) / 4.0f;

            Vector3 AA91 = (A91 + A92 + v41 + v4) / 4.0f;
            Vector3 AA92 = (A92 + A93 + v43 + v4) / 4.0f;
            Vector3 AA93 = (A93 + A71 + v45 + v4) / 4.0f;
            Vector3 AA9Last;
            if (val4 == 3)
                AA9Last = (A91 + A71 + v41 + v4) / 4.0f;
            else if (val4 == 4)
                AA9Last = (A92 + A71 + v43 + v4) / 4.0f;
            else
                AA9Last = (A93 + A71 + v45 + v4) / 4.0f;
            Vector3 AA9First;
            if (val4 == 3)
                AA9First = (A91 + A71 + v41 + v4) / 4.0f;
            else
                AA9First = (A91 + A92 + v41 + v4) / 4.0f;

            Vector3 AA71 = (A71 + A72 + v31 + v3) / 4.0f;
            Vector3 AA72 = (A72 + A73 + v33 + v3) / 4.0f;
            Vector3 AA73 = (A73 + A11 + v35 + v3) / 4.0f;
            Vector3 AA7Last;
            if (val3 == 3)
                AA7Last = (A71 + A11 + v31 + v3) / 4.0f;
            else if (val3 == 4)
                AA7Last = (A72 + A11 + v33 + v3) / 4.0f;
            else
                AA7Last = (A73 + A11 + v35 + v3) / 4.0f;
            Vector3 AA7First;
            if (val3 == 3)
                AA7First = (A71 + A11 + v31 + v3) / 4.0f;
            else
                AA7First = (A71 + A72 + v31 + v3) / 4.0f;



            //*****************
            b7 = (a1 + a2 + a4 + a5) / 4;
            b9 = (a2 + a3 + a5 + a6) / 4;
            b17 = (a4 + a5 + a7 + a8) / 4;
            b19 = (a5 + a6 + a8 + a9) / 4;
            b8 = (a2 + a5 + b7 + b9) / 4;
            b12 = (a4 + a5 + b7 + b17) / 4;
            b14 = (a5 + a6 + b9 + b19) / 4;
            b18 = (a5 + a8 + b17 + b19) / 4;
            b13 = 0.5f * a5 + (b7 + b8 + b9 + b12 + b14 + b17 + b18 + b19) / 16;

            // *****
            b2 = (a1 + a2 + b7 + (a1 + a2 + A31 + AA1Last) / 4) / 4;
            b4 = (a2 + a3 + b9 + (a2 + a3 + A31 + AA3First) / 4) / 4;
            b3 = (36 * a2 + 6 * (a1 + a3 + a5 + A31) + a4 + a6 + AA1Last + AA3First) / 64;
            if (val1 == 3)
                b1 = (15 * a1 + 6 * (AA1Last + a2 + a4) + A11 + a5 + A31) / 36;
            else if (val1 == 4)
                b1 = (36 * a1 + 6 * (AA11 + AA1Last + a2 + a4) + A11 + A12 + a5 + A31) / 64;
            else
                b1 = (65 * a1 + 6 * (AA11 + AA12 + AA1Last + a2 + a4) + A11 + A12 + A13 + a5 + A31) / 100;


            b10 = (a3 + a6 + b9 + (a3 + a6 + A91 + AA3Last) / 4) / 4;
            b20 = (a6 + a9 + b19 + (a6 + a9 + A91 + AA9First) / 4) / 4;
            b15 = (36 * a6 + 6 * (a5 + a3 + a9 + A91) + a2 + a8 + AA3Last + AA9First) / 64;
            if (val2 == 3)
                b5 = (15 * a3 + 6 * (AA3Last + a2 + a6) + A31 + a5 + A91) / 36;
            else if (val2 == 4)
                b5 = (36 * a3 + 6 * (AA31 + AA3Last + a2 + a6) + A31 + A32 + a5 + A91) / 64;
            else
                b5 = (65 * a3 + 6 * (AA31 + AA32 + AA3Last + a2 + a6) + A31 + A32 + A33 + a5 + A91) / 100;


            b24 = (a8 + a9 + b19 + (a8 + a9 + A71 + AA9Last) / 4) / 4;
            b22 = (a7 + a8 + b17 + (a7 + a8 + A71 + AA7First) / 4) / 4;
            b23 = (36 * a8 + 6 * (a5 + a7 + a9 + A71) + a4 + a6 + AA9Last + AA7First) / 64;
            if (val4 == 3)
                b25 = (15 * a9 + 6 * (AA9Last + a6 + a8) + A91 + a5 + A71) / 36;
            else if (val4 == 4)
                b25 = (36 * a9 + 6 * (AA91 + AA9Last + a6 + a8) + A91 + A92 + a5 + A71) / 64;
            else
                b25 = (65 * a9 + 6 * (AA91 + AA92 + AA9Last + a6 + a8) + A91 + A92 + A93 + a5 + A71) / 100;


            b16 = (a4 + a7 + b17 + (a4 + a7 + A11 + AA7Last) / 4) / 4;
            b6 = (a1 + a4 + b7 + (a1 + a4 + A11 + AA1First) / 4) / 4;
            b11 = (36 * a4 + 6 * (a1 + a5 + a7 + A11) + a2 + a8 + AA7Last + AA1First) / 64;
            if (val3 == 3)
                b21 = (15 * a7 + 6 * (AA7Last + a4 + a8) + A71 + a5 + A11) / 36;
            else if (val3 == 4)
                b21 = (36 * a7 + 6 * (AA71 + AA7Last + a4 + a8) + A71 + A72 + a5 + A11) / 64;
            else
                b21 = (65 * a7 + 6 * (AA71 + AA72 + AA7Last + a4 + a8) + A71 + A72 + A73 + a5 + A11) / 100;



            // ********** texture and normal
            Vector2 t1 = g_texUvBuffer[texInd.x];
            Vector2 t5 = g_texUvBuffer[texInd.y];
            Vector2 t21 = g_texUvBuffer[texInd.z];
            Vector2 t25 = g_texUvBuffer[texInd.w];
            Vector2 t11 = (t1 + t21) / 2.0f;
            Vector2 t6 = (t1 + t11) / 2.0f;
            Vector2 t16 = (t11 + t21) / 2.0f;
            Vector2 t15 = (t5 + t25) / 2.0f;
            Vector2 t10 = (t5 + t15) / 2.0f;
            Vector2 t20 = (t15 + t25) / 2.0f;
            Vector2 t3 = (t1 + t5) / 2.0f;
            Vector2 t2 = (t1 + t3) / 2.0f;
            Vector2 t4 = (t3 + t5) / 2.0f;
            Vector2 t8 = (t6 + t10) / 2.0f;
            Vector2 t7 = (t6 + t8) / 2.0f;
            Vector2 t9 = (t8 + t10) / 2.0f;
            Vector2 t13 = (t11 + t15) / 2.0f;
            Vector2 t12 = (t11 + t13) / 2.0f;
            Vector2 t14 = (t13 + t15) / 2.0f;
            Vector2 t18 = (t16 + t20) / 2.0f;
            Vector2 t17 = (t16 + t18) / 2.0f;
            Vector2 t19 = (t18 + t20) / 2.0f;
            Vector2 t23 = (t21 + t25) / 2.0f;
            Vector2 t22 = (t21 + t23) / 2.0f;
            Vector2 t24 = (t23 + t25) / 2.0f;

            Vector3 n1 = g_normalBuffer[normalInd.x];
            Vector3 n5 = g_normalBuffer[normalInd.y];
            Vector3 n21 = g_normalBuffer[normalInd.z];
            Vector3 n25 = g_normalBuffer[normalInd.w];
            Vector3 n11 = (n1 + n21) / 2.0f;
            Vector3 n6 = (n1 + n11) / 2.0f;
            Vector3 n16 = (n11 + n21) / 2.0f;
            Vector3 n15 = (n5 + n25) / 2.0f;
            Vector3 n10 = (n5 + n15) / 2.0f;
            Vector3 n20 = (n15 + n25) / 2.0f;
            Vector3 n3 = (n1 + n5) / 2.0f;
            Vector3 n2 = (n1 + n3) / 2.0f;
            Vector3 n4 = (n3 + n5) / 2.0f;
            Vector3 n8 = (n6 + n10) / 2.0f;
            Vector3 n7 = (n6 + n8) / 2.0f;
            Vector3 n9 = (n8 + n10) / 2.0f;
            Vector3 n13 = (n11 + n15) / 2.0f;
            Vector3 n12 = (n11 + n13) / 2.0f;
            Vector3 n14 = (n13 + n15) / 2.0f;
            Vector3 n18 = (n16 + n20) / 2.0f;
            Vector3 n17 = (n16 + n18) / 2.0f;
            Vector3 n19 = (n18 + n20) / 2.0f;
            Vector3 n23 = (n21 + n25) / 2.0f;
            Vector3 n22 = (n21 + n23) / 2.0f;
            Vector3 n24 = (n23 + n25) / 2.0f;

            // first row
            output.Position = b5;
            output.TextureCoordinate = t5;
            output.Normal = n5;
            m_triangleStrip.Add(output);

            output.Position = b10;
            output.TextureCoordinate = t10;
            output.Normal = n10;
            m_triangleStrip.Add(output);

            output.Position = b4;
            output.TextureCoordinate = t4;
            output.Normal = n4;
            m_triangleStrip.Add(output);

            output.Position = b9;
            output.TextureCoordinate = t9;
            output.Normal = n9;
            m_triangleStrip.Add(output);

            output.Position = b3;
            output.TextureCoordinate = t3;
            output.Normal = n3;
            m_triangleStrip.Add(output);

            output.Position = b8;
            output.TextureCoordinate = t8;
            output.Normal = n8;
            m_triangleStrip.Add(output);

            output.Position = b2;
            output.TextureCoordinate = t2;
            output.Normal = n2;
            m_triangleStrip.Add(output);

            output.Position = b7;
            output.TextureCoordinate = t7;
            output.Normal = n7;
            m_triangleStrip.Add(output);

            output.Position = b1;
            output.TextureCoordinate = t1;
            output.Normal = n1;
            m_triangleStrip.Add(output);

            output.Position = b6;
            output.TextureCoordinate = t6;
            output.Normal = n6;
            m_triangleStrip.Add(output);

            RestartStrip();

            // second row
            output.Position = b10;
            output.TextureCoordinate = t10;
            output.Normal = n10;
            m_triangleStrip.Add(output);

            output.Position = b15;
            output.TextureCoordinate = t15;
            output.Normal = n15;
            m_triangleStrip.Add(output);

            output.Position = b9;
            output.TextureCoordinate = t9;
            output.Normal = n9;
            m_triangleStrip.Add(output);

            output.Position = b14;
            output.TextureCoordinate = t14;
            output.Normal = n14;
            m_triangleStrip.Add(output);

            output.Position = b8;
            output.TextureCoordinate = t8;
            output.Normal = n8;
            m_triangleStrip.Add(output);

            output.Position = b13;
            output.TextureCoordinate = t13;
            output.Normal = n13;
            m_triangleStrip.Add(output);

            output.Position = b7;
            output.TextureCoordinate = t7;
            output.Normal = n7;
            m_triangleStrip.Add(output);

            output.Position = b12;
            output.TextureCoordinate = t12;
            output.Normal = n12;
            m_triangleStrip.Add(output);

            output.Position = b6;
            output.TextureCoordinate = t6;
            output.Normal = n6;
            m_triangleStrip.Add(output);

            output.Position = b11;
            output.TextureCoordinate = t11;
            output.Normal = n11;
            m_triangleStrip.Add(output);

            RestartStrip();

            // third row
            output.Position = b15;
            output.TextureCoordinate = t15;
            output.Normal = n15;
            m_triangleStrip.Add(output);

            output.Position = b20;
            output.TextureCoordinate = t20;
            output.Normal = n20;
            m_triangleStrip.Add(output);

            output.Position = b14;
            output.TextureCoordinate = t14;
            output.Normal = n14;
            m_triangleStrip.Add(output);

            output.Position = b19;
            output.TextureCoordinate = t19;
            output.Normal = n19;
            m_triangleStrip.Add(output);

            output.Position = b13;
            output.TextureCoordinate = t13;
            output.Normal = n13;
            m_triangleStrip.Add(output);

            output.Position = b18;
            output.TextureCoordinate = t18;
            output.Normal = n18;
            m_triangleStrip.Add(output);

            output.Position = b12;
            output.TextureCoordinate = t12;
            output.Normal = n12;
            m_triangleStrip.Add(output);

            output.Position = b17;
            output.TextureCoordinate = t17;
            output.Normal = n17;
            m_triangleStrip.Add(output);

            output.Position = b11;
            output.TextureCoordinate = t11;
            output.Normal = n11;
            m_triangleStrip.Add(output);

            output.Position = b16;
            output.TextureCoordinate = t16;
            output.Normal = n16;
            m_triangleStrip.Add(output);

            RestartStrip();

            // fourth row
            output.Position = b20;
            output.TextureCoordinate = t20;
            output.Normal = n20;
            m_triangleStrip.Add(output);

            output.Position = b25;
            output.TextureCoordinate = t25;
            output.Normal = n25;
            m_triangleStrip.Add(output);

            output.Position = b19;
            output.TextureCoordinate = t19;
            output.Normal = n19;
            m_triangleStrip.Add(output);

            output.Position = b24;
            output.TextureCoordinate = t24;
            output.Normal = n24;
            m_triangleStrip.Add(output);

            output.Position = b18;
            output.TextureCoordinate = t18;
            output.Normal = n18;
            m_triangleStrip.Add(output);

            output.Position = b23;
            output.TextureCoordinate = t23;
            output.Normal = n23;
            m_triangleStrip.Add(output);

            output.Position = b17;
            output.TextureCoordinate = t17;
            output.Normal = n17;
            m_triangleStrip.Add(output);

            output.Position = b22;
            output.TextureCoordinate = t22;
            output.Normal = n22;
            m_triangleStrip.Add(output);

            output.Position = b16;
            output.TextureCoordinate = t16;
            output.Normal = n16;
            m_triangleStrip.Add(output);

            output.Position = b21;
            output.TextureCoordinate = t21;
            output.Normal = n21;
            m_triangleStrip.Add(output);

            RestartStrip();


        }

        

       



    }
}
